package net.guerlab.smart.wx.service.service.impl;

import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import net.guerlab.commons.exception.ApplicationException;
import net.guerlab.smart.wx.core.domain.LoginResponse;
import net.guerlab.smart.wx.core.exception.CodeInvalidException;
import net.guerlab.smart.wx.service.entity.WxApp;
import net.guerlab.smart.wx.service.entity.WxUser;
import net.guerlab.smart.wx.service.service.WxMpLoginService;
import net.guerlab.smart.wx.service.service.WxMpManagerService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;

/**
 * 微信公众号登录服务实现
 *
 * @author guer
 */
@Service
public class WxMpLoginServiceImpl extends AbstractWxLoginServiceImpl implements WxMpLoginService {

    private WxMpManagerService managerService;

    @Override
    public LoginResponse login(String appId, String code, String ip, String referer) {
        if (StringUtils.isBlank(code)) {
            throw new CodeInvalidException();
        }

        WxApp wxApp = getWxApp(appId);
        WxMpService wxMpService = getWxMpService(appId);
        WxMpUser wxMpUser;

        try {
            WxMpOAuth2AccessToken oAuth2AccessToken = wxMpService.oauth2getAccessToken(code);
            wxMpUser = wxMpService.oauth2getUserInfo(oAuth2AccessToken, "zh_CN");
        } catch (WxErrorException e) {
            throw new ApplicationException(e.getError().getErrorMsg(), e.getError().getErrorCode());
        }

        String unionId = wxMpUser.getUnionId();
        String openId = wxMpUser.getOpenId();

        WxUser wxUser = wxUserService.findUser(appId, openId);
        if (wxUser == null) {
            LocalDateTime now = LocalDateTime.now();
            wxUser = new WxUser();
            wxUser.setOpenId(openId);
            wxUser.setAppId(appId);
            wxUser.setAppName(wxApp.getAppName());
            wxUser.setUnionId(unionId);
            wxUser.setAvatarUrl(wxMpUser.getHeadImgUrl());
            wxUser.setNickName(wxMpUser.getNickname());
            wxUser.setRegistryTime(now);
            wxUser.setLastLoginTime(now);
            wxUser.setActivated(true);
            wxUserService.insertSelective(wxUser);
            wxUserLoginLogService.addLog(wxUser, ip, referer);
        } else {
            wxUser.setActivated(true);
            updateUserInfo(wxUser, openId, unionId, true, ip, referer);
        }

        return buildLoginResponse(wxUser);
    }

    private WxMpService getWxMpService(String appId) {
        return managerService.getService(appId);
    }

    @Autowired
    public void setManagerService(WxMpManagerService managerService) {
        this.managerService = managerService;
    }
}
